package kr.ac.konkuk.db.quadtree.node;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import kr.ac.konkuk.db.quadtree.QuadTree;
import kr.ac.konkuk.db.quadtree.RowKey;
import kr.ac.konkuk.db.quadtree.callback.GeometryProvider;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;


public class LeafNode extends NodeBase {
	private int count = 0;
//	private Map<RowKey, Set<Coordinate>> datas = Collections.synchronizedMap(new HashMap<RowKey, Set<Coordinate>>());
	private Set<RowKey> datas = Collections.synchronizedSet(new HashSet<RowKey>());
	
	public LeafNode(String cf, Envelope env, GeometryProvider provider) {
		super(cf, env, provider);
	}
	
	public void split(Node newNode) {
		for (RowKey rowKey : datas) {
			Geometry geom = geometryProvider.getGeometry(rowKey);
			if (geom == null)
				throw new NullPointerException("GeometryProvider::getGeometry() must be not null");
			Coordinate[] coords = geom.getCoordinates();
			for (Coordinate coord : coords) {
				newNode.put(rowKey, coord, null);
			}
		}
	}
	
	public void put(RowKey rowKey, Coordinate coord, Set<String> cfSet) {
		if (!datas.contains(rowKey)) {
			datas.add(rowKey);
		}
		if (cfSet != null) {
			cfSet.add(this.columnFamily());
		}
		count++;
	}
	
	public boolean isSplit() {
		return count > QuadTree.COUNT_FOR_SPLIT;
	}
	
	public void search(Envelope searchEnv, NodeVisitor visitor) {
		visitor.visit(this);
	}
	
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append(super.toString())
			.append("@LeafNode[count=")
			.append(count)
			.append("]");
		
		return sb.toString();
	}
	
	public Collection<Coordinate> remove(RowKey rowKey, Coordinate coord) {
		if (datas.contains(rowKey)) {
			Geometry geom = geometryProvider.getGeometry(rowKey);
			if (geom == null)
				throw new NullPointerException("GeometryProvider::getGeometry() must be not null");
			Coordinate[] oldCoords = geom.getCoordinates();
			datas.remove(rowKey);
			return Arrays.asList(oldCoords);
		}
		
		return Collections.emptySet();
	}

}
